#pragma once 
#include <iostream>
#include <string>
#include <cstring>
#include <cerrno>
#include <cstdlib>
#include <strings.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include "err.hpp"

using namespace std;

namespace nt_client
{
    class UdpClient
    {
    public:
        UdpClient(const string& ip, uint16_t port)
            :server_ip_(ip), server_port_(port)
        {

        }    

        ~UdpClient()
        {

        }

        void InitClient()
        {
            sock_ = socket(AF_INET, SOCK_DGRAM, 0);
            if(sock_ == -1)
            {
                cout << "Creat Socket Fail: " << strerror(errno) << endl;
                exit(SOCKET_ERR);
            }
            cout << "Create Success Socket: " << sock_ << endl;

            bzero(&svr_, sizeof(svr_));
            svr_.sin_family = AF_INET; // 设置为网络通信（PF_INET 也行）
            svr_.sin_addr.s_addr = inet_addr(server_ip_.c_str()); // 绑定服务器IP地址
            svr_.sin_port = htons(server_port_); // 绑定服务器端口号
        }

        void StartClient()
        {
            char buff[1024];

            while(true)
            {
                // 1.发送消息
                std::string msg;
                std::cout << "Input Message# ";
                std::getline(std::cin, msg);

                ssize_t n = sendto(sock_, msg.c_str(), msg.size(), 0, (const struct sockaddr*)&svr_, sizeof(svr_));

                if(n == -1)
                {
                    std::cout << "Send Message Fail: " << strerror(errno) << std::endl;
                    continue; // 重新输入消息并发送
                }

                // 2.接收消息
                socklen_t len = sizeof(svr_); // 创建一个变量，因为接下来的参数需要传左值
                n = recvfrom(sock_, buff, sizeof(buff) - 1, 0, (struct sockaddr*)&svr_, &len);

                if(n > 0)
                    buff[n] = '\0';
                else
                    continue;

                // 可以再次获取IP地址与端口号
                std::string ip = inet_ntoa(svr_.sin_addr);
                uint16_t port = ntohs(svr_.sin_port);

                printf("Client get message from [%s:%d]# %s\n",ip.c_str(), port, buff);

                        
        }    
    }

    private:
        string server_ip_;
        uint16_t server_port_;
        int sock_;
        struct sockaddr_in svr_;
    };
}
